package com.stockz.ui.swing.charting.display.indicator;

import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.stockz.core.model.Bar;
import com.stockz.core.util.BarUtil;
import com.stockz.core.util.BarUtil.BarValueType;
import com.stockz.core.util.ListUtil;
import com.stockz.indicator.volume.PriceRange;
import com.stockz.ui.swing.charting.painter.indicator.VolumeIndicatorPainter;
import com.stockz.ui.swing.charting.util.MathUtil;
import com.stockz.ui.swing.charting.util.UIChartingConstant.OVERLAY;
import com.stockz.ui.swing.charting.view.StockChartPanelState;

@Component
@Scope("prototype")
public class Volume extends AbstractDisplayableIndicatorConfiguration {
	public static class Configuration{
		private double percentage = 5;
		private int devisions = 20;
		private boolean weighed;
		
		public double getPercentage() {
			return percentage;
		}
		public void setPercentage(double percentage) {
			this.percentage = percentage;
		}
		public int getDevisions() {
			return devisions;
		}
		public void setDevisions(int devisions) {
			this.devisions = devisions;
		}
		public boolean isWeighed() {
			return weighed;
		}
		public void setWeighed(boolean weighed) {
			this.weighed = weighed;
		}
	}
	
	public static List<PriceRange> getPriceRangeList(List<Bar> barList, 
			Configuration configuration, BarValueType barValueType){

		if(barList == null || barList.size() == 0){
			return null;
		}
		
		double min = MathUtil.min(ListUtil.convert(barList, BarValueType.LOW));
		double max = MathUtil.max(ListUtil.convert(barList, BarValueType.HIGH));
		List<PriceRange> priceRangeList = preparePriceRangeListUsingDivisions(min,max,configuration);
		for(PriceRange priceRange : priceRangeList){
			double valueSum = 0;
			for(int i = 1; i <= barList.size(); i++){
				Bar bar = barList.get(i-1);
				if(bar.getClose() < priceRange.getUpperLimit()
						&& bar.getClose() >= priceRange.getLowerLimit()){
					if(configuration.isWeighed()){
						valueSum += (BarUtil.getValue(bar,barValueType)/i);
					}else{
						valueSum += (BarUtil.getValue(bar,barValueType));
					}
				}
			}
			priceRange.setValue(valueSum);
		}
		return priceRangeList;
	}
	
	public static List<PriceRange> preparePriceRangeList(double[] valueArray,Configuration configuration){
		double max = MathUtil.max(valueArray);
		double min = MathUtil.min(valueArray);
		return preparePriceRangeListUsingDivisions(min,max,configuration);
	}
	
	
	public static List<PriceRange> preparePriceRangeListUsingPercentage(double min, double max,Configuration configuration){
		List<PriceRange> priceRangeList = new ArrayList<PriceRange>();
		while(max > min){
			double upperLimit = min*((configuration.getPercentage()+100)/100);
			PriceRange priceRange = new PriceRange(upperLimit,min);
			priceRangeList.add(priceRange);
			min = upperLimit;
		}
		return priceRangeList;
	}
	
	public static List<PriceRange> preparePriceRangeListUsingDivisions(double min, double max,Configuration configuration){
		List<PriceRange> priceRangeList = new ArrayList<PriceRange>(configuration.getDevisions());
		double range = (max - min)/configuration.getDevisions();
		for(int i = 0; i < configuration.getDevisions(); i++){
			PriceRange priceRange = new PriceRange((i+1)*range+min,i*range+min);
			priceRangeList.add(priceRange);
		}
		return priceRangeList;
	}
	
	
	private Configuration configuration = new Configuration();

	@Override
	public Object getConfiguration() {
		return configuration;
	}
	
	@Override
	public String getFullName() {
		return "Volume Indicator";
	}

	@Override
	public String getShortName() {
		return "VOL";
	}

	@Override
	public OVERLAY getOverlay() {
		return OVERLAY.PRICE;
	}

	@Override
	public void refreshValues() {
		
	}

	public List<PriceRange> getPriceRangeList(){
		StockChartPanelState state = getStockChartPanel().getStockChartPanelState();
		List<Bar> barList = state.getBarList().subList(state.getStartIndex(), state.getEndIndex());
		return getPriceRangeList(barList,configuration,getBarValueType());
	}
	
	@Override
	public String getDescription() {
		return getShortName()+","+configuration.getDevisions();
	}

	@Override
	public void paint(Graphics2D g) {
		VolumeIndicatorPainter.paint(g, this);
	}

	@Override
	public boolean isOverlappable() {
		return false;
	}

}
